import { writeFile } from 'fs/promises';
import path from 'path';
import { mkdir } from 'fs/promises';
import { getDefaultOssClient, AliOssUtil } from '../aliOss';

export interface FileStorageResult {
  url: string;
  fileName: string;
  originalName: string;
  type: string;
  size: number;
  path?: string;
}

export interface FileStorageOptions {
  type: 'image' | 'video' | 'model';
  date?: string;
}

/**
 * 文件存储服务接口
 */
export interface FileStorageService {
  uploadFile(file: File, options: FileStorageOptions): Promise<FileStorageResult>;
  getFileUrl(filePath: string): string;
}

/**
 * 本地文件存储服务
 */
export class LocalFileStorage implements FileStorageService {
  private basePath: string;
  private baseUrl: string;

  constructor() {
    this.basePath = path.join(process.cwd(), 'public', 'uploads');
    this.baseUrl = '/api/uploads';
  }

  async uploadFile(file: File, options: FileStorageOptions): Promise<FileStorageResult> {
    const { type, date = getCurrentDayInShanghai() } = options;

    // 创建文件保存目录
    const uploadDir = path.join(this.basePath, type, date);
    await mkdir(uploadDir, { recursive: true });

    // 生成唯一文件名
    const timestamp = Date.now();
    const originalName = file.name;
    const fileName = `${timestamp}-${originalName}`;
    const filePath = path.join(uploadDir, fileName);
    
    // 获取文件的二进制数据
    const bytes = await file.arrayBuffer();
    const buffer = Buffer.from(bytes);

    // 写入文件到服务器
    await writeFile(filePath, buffer);

    // 返回可访问的URL
    const fileUrl = `${this.baseUrl}/${type}/${date}/${fileName}`;
    
    return {
      url: fileUrl,
      fileName,
      originalName: file.name,
      type,
      size: file.size,
      path: `${type}/${date}/${fileName}`
    };
  }

  getFileUrl(filePath: string): string {
    return `${this.baseUrl}/${filePath}`;
  }
}

/**
 * 阿里云OSS文件存储服务
 */
export class OssFileStorage implements FileStorageService {
  private ossClient: AliOssUtil;

  constructor() {
    this.ossClient = getDefaultOssClient();
  }

  async uploadFile(file: File, options: FileStorageOptions): Promise<FileStorageResult> {
    const { type, date = getCurrentDayInShanghai() } = options;
    
    // 构建OSS路径
    const ossDirectory = `uploads/${type}/${date}`;

    
    
    // 上传到OSS
    const result = await this.ossClient.uploadFile(file, ossDirectory);
   
    
    if (!result.success) {
      throw new Error('文件上传失败: ' + (result.error ? result.error.message : '未知错误'));
    }
    
    return {
      url: result.url,
      fileName: result.name,
      originalName: file.name,
      type,
      size: file.size,
      path: result.path
    };
  }

  getFileUrl(filePath: string): string {
    // 如果是完整URL，直接返回
    if (filePath.startsWith('http')) {
      return filePath;
    }
    return `${this.ossClient['baseUrl']}${filePath}`;
  }
}

// 辅助函数：获取上海时间的当前日期，格式为YYYY-MM-DD
export function getCurrentDayInShanghai(): string {
  const now = new Date();
  const shanghaiTime = new Date(now.getTime() + (8 * 60 * 60 * 1000));
  return shanghaiTime.toISOString().split('T')[0];
}

// 辅助函数：获取上海时间的当前时间，格式为YYYY-MM-DD HH:mm:ss
export function getCurrentTimeInShanghai(): string {
  const now = new Date();
  const shanghaiTime = new Date(now.getTime() + (8 * 60 * 60 * 1000));
  return shanghaiTime.toISOString().replace('T', ' ').substring(0, 19);
}

/**
 * 获取文件存储服务实例
 */
export function getStorageService(): FileStorageService {
  // 根据环境变量决定使用哪种存储方式
  const useOss = process.env.USE_OSS === 'true';
  
  if (useOss) {
    try {
      return new OssFileStorage();
    } catch (error) {
      console.error('OSS初始化失败，回退到本地存储:', error);
      return new LocalFileStorage();
    }
  }
  
  return new LocalFileStorage();
}

export default getStorageService;

/**
 * 文件操作工具类
 */
export class FileOperationUtil {
  private static storageService = getStorageService();
  
  /**
   * 判断是否为OSS URL
   */
  static isOssUrl(url: string): boolean {
    return url.startsWith('http://') || url.startsWith('https://');
  }
  
  /**
   * 判断是否为本地URL
   */
  static isLocalUrl(url: string): boolean {
    return url.startsWith('/api/uploads/');
  }
  
  /**
   * 从URL下载文件并转换为Buffer
   * @param url 文件URL（支持本地和OSS）
   * @returns 文件Buffer
   */
  static async downloadFileToBuffer(url: string): Promise<Buffer> {
    if (this.isOssUrl(url)) {
      // 从OSS下载文件
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error(`下载文件失败: ${response.status} - ${response.statusText}`);
      }
      const arrayBuffer = await response.arrayBuffer();
      return Buffer.from(arrayBuffer);
    } else {
      // 从本地文件系统读取
      const fs = await import('fs/promises');
      const path = await import('path');
      
      // 构建文件系统绝对路径（去掉 '/api' 前缀）
      const fileUrl = url.startsWith('/api') ? url.slice(4) : url;
      const absolutePath = path.join(process.cwd(), 'public', fileUrl);
      
      return await fs.readFile(absolutePath);
    }
  }
  
  /**
   * 删除文件（支持本地和OSS）
   * @param url 文件URL
   * @returns 删除是否成功
   */
  static async deleteFile(url: string): Promise<boolean> {
    try {
      if (this.isOssUrl(url)) {
        // 删除OSS文件
        if (this.storageService instanceof OssFileStorage) {
          const ossPath = this.extractOssPathFromUrl(url);
          if (ossPath) {
            return await (this.storageService as any).ossClient.deleteFile(ossPath);
          }
        }
        return false;
      } else {
        // 删除本地文件
        const fs = await import('fs');
        const path = await import('path');
        
        const fileUrl = url.startsWith('/api') ? url.slice(4) : url;
        const absolutePath = path.join(process.cwd(), 'public', fileUrl);
        
        if (fs.existsSync(absolutePath)) {
          fs.unlinkSync(absolutePath);
          return true;
        }
        return false;
      }
    } catch (error) {
      console.error(`删除文件失败: ${url}`, error);
      return false;
    }
  }
  
  /**
   * 从OSS URL中提取文件路径
   * @param url OSS URL
   * @returns OSS文件路径
   */
  private static extractOssPathFromUrl(url: string): string | null {
    try {
      const urlObj = new URL(url);
      // 去掉开头的斜杠
      return urlObj.pathname.startsWith('/') ? urlObj.pathname.slice(1) : urlObj.pathname;
    } catch {
      return null;
    }
  }
  
  /**
   * 批量删除文件
   * @param urls 文件URL数组
   * @returns 删除成功的数量
   */
  static async deleteMultipleFiles(urls: string[]): Promise<number> {
    let successCount = 0;
    
    // 分别处理OSS和本地文件
    const ossUrls = urls.filter(url => this.isOssUrl(url));
    const localUrls = urls.filter(url => this.isLocalUrl(url));
    
    // 批量删除OSS文件
    if (ossUrls.length > 0 && this.storageService instanceof OssFileStorage) {
      const ossPaths = ossUrls
        .map(url => this.extractOssPathFromUrl(url))
        .filter(path => path !== null) as string[];
      
      if (ossPaths.length > 0) {
        try {
          const results = await (this.storageService as any).ossClient.deleteMultiple(ossPaths);
          successCount += results.filter(Boolean).length;
        } catch (error) {
          console.error('批量删除OSS文件失败:', error);
        }
      }
    }
    
    // 删除本地文件
    for (const url of localUrls) {
      if (await this.deleteFile(url)) {
        successCount++;
      }
    }
    
    return successCount;
  }
} 